home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / lysrc.zip / YACCBASE.PAS < prev    next >
Pascal/Delphi Source File  |  1993-01-24  |  19KB  |  703 lines

  1.  
  2. unit YaccBase;
  3.  
  4. (* 2-16-91 AG *)
  5.  
  6. (* Copyright (c) 1990,91 by Albert Graef, Schillerstr. 18,
  7.    6509 Schornsheim/Germany
  8.    All rights reserved *)
  9.  
  10. interface
  11.  
  12. (* This module collects the basic data types and operations used in the TP
  13.    Yacc program, and other basic stuff that does not belong anywhere else:
  14.    - Yacc input and output files and corresponding bookkeeping information
  15.      used by the parser
  16.    - symbolic character constants
  17.    - dynamically allocated strings
  18.    - integer sets
  19.    - generic quicksort and hash table routines
  20.    - utilities for list-generating
  21.    - other tiny utilities *)
  22.  
  23. const
  24.  
  25. (* symbolic character constants: *)
  26.  
  27. bs   = #8;    (* backspace character *)
  28. tab  = #9;    (* tab character *)
  29. nl   = #10;    (* newline character *)
  30. cr   = #13;    (* carriage return *)
  31. ff   = #12;    (* form feed character *)
  32.  
  33. var
  34.  
  35. (* Filenames: *)
  36.  
  37. yfilename     : String;
  38. pasfilename   : String;
  39. lstfilename   : String;
  40. codfilename   : String;
  41.  
  42. (* Yacc input, output, list and code template file: *)
  43.  
  44. yyin, yyout, yylst, yycod : Text;
  45.  
  46. (* the following values are initialized and updated by the parser: *)
  47.  
  48. line      : String;  (* current input line *)
  49. lno, cno  : Integer; (* current input position (line/column) *)
  50. tokleng   : Integer; (* length of current token *)
  51.  
  52. const
  53.  
  54. max_elems  = 50;  (* maximum size of integer sets *)
  55.  
  56. type
  57.  
  58. (* String pointers: *)
  59.  
  60. StrPtr    = ^String;
  61.  
  62. (* Sorted integer sets: *)
  63.  
  64. IntSet    = array [0..max_elems] of Integer;
  65.               (* word 0 is size *)
  66. IntSetPtr = ^IntSet;
  67.  
  68. (* Operations: *)
  69.  
  70. (* Strings pointers: *)
  71.  
  72. function newStr(str : String) : StrPtr;
  73.   (* creates a string pointer (only the space actually needed for the given
  74.      string is allocated) *)
  75.  
  76. (* Integer sets (set arguments are passed by reference even if they are not
  77.    modified, for greater efficiency): *)
  78.  
  79. procedure empty(var M : IntSet);
  80.   (* initializes M as empty *)
  81. procedure singleton(var M : IntSet; i : Integer);
  82.   (* initializes M as a singleton set containing the element i *)
  83. procedure include(var M : IntSet; i : Integer);
  84.   (* include i in M *)
  85. procedure exclude(var M : IntSet; i : Integer);
  86.   (* exclude i from M *)
  87. procedure setunion(var M, N : IntSet);
  88.   (* adds N to M *)
  89. procedure setminus(var M, N : IntSet);
  90.   (* removes N from M *)
  91. procedure intersect(var M, N : IntSet);
  92.   (* removes from M all elements NOT in N *)
  93. function size(var M : IntSet) : Integer;
  94.   (* cardinality of set M *)
  95. function member(i : Integer; var M : IntSet) : Boolean;
  96.   (* tests for membership of i in M *)
  97. function isempty(var M : IntSet) : Boolean;
  98.   (* checks whether M is an empty set *)
  99. function equal(var M, N : IntSet) : Boolean;
  100.   (* checks whether M and N are equal *)
  101. function subseteq(var M, N : IntSet) : Boolean;
  102.   (* checks whether M is a subset of N *)
  103. function newEmptyIntSet : IntSetPtr;
  104.   (* creates a pointer to an empty integer set *)
  105. function newIntSet ( var M : IntSet ) : IntSetPtr;
  106.   (* creates a dynamic copy of M (only the space actually needed
  107.      is allocated) *)
  108.  
  109. (* Quicksort: *)
  110.  
  111. type
  112.  
  113. OrderPredicate = function (i, j : Integer) : Boolean;
  114. SwapProc = procedure (i, j : Integer);
  115.  
  116. procedure quicksort(lo, hi: Integer;
  117.                     less : OrderPredicate;
  118.                     swap : SwapProc);
  119.   (* General inplace sorting procedure based on the quicksort algorithm.
  120.      This procedure can be applied to any sequential data structure;
  121.      only the corresponding routines less which compares, and swap which
  122.      swaps two elements i,j of the target data structure, must be
  123.      supplied as appropriate for the target data structure.
  124.      - lo, hi: the lower and higher indices, indicating the elements to
  125.        be sorted
  126.      - less(i, j): should return true if element no. i `is less than'
  127.        element no. j, and false otherwise; any total quasi-ordering may
  128.        be supplied here (if neither less(i, j) nor less(j, i) then elements
  129.        i and j are assumed to be `equal').
  130.      - swap(i, j): should swap the elements with index i and j *)
  131.  
  132. (* Generic hash table routines (based on quadratic rehashing; hence the
  133.    table size must be a prime number): *)
  134.  
  135. type
  136.  
  137. TableLookupProc = function(k : Integer) : String;
  138. TableEntryProc  = procedure(k : Integer; symbol : String);
  139.  
  140. function key(symbol : String;
  141.              table_size : Integer;
  142.              lookup : TableLookupProc;
  143.              entry  : TableEntryProc) : Integer;
  144.   (* returns a hash table key for symbol; inserts the symbol into the
  145.      table if necessary
  146.      - table_size is the symbol table size and must be a fixed prime number
  147.      - lookup is the table lookup procedure which should return the string
  148.        at key k in the table ('' if entry is empty)
  149.      - entry is the table entry procedure which is assumed to store the
  150.        given symbol at the given location *)
  151.  
  152. function definedKey(symbol : String;
  153.                     table_size : Integer;
  154.                     lookup : TableLookupProc) : Boolean;
  155.   (* checks the table to see if symbol is in the table *)
  156.  
  157. (* Utility routines: *)
  158.  
  159. function min(i, j : Integer) : Integer;
  160. function max(i, j : Integer) : Integer;
  161.   (* minimum and maximum of two integers *)
  162. function upper(str : String) : String;
  163.   (* returns str converted to uppercase *)
  164. function strip(str : String) : String;
  165.   (* returns str with leading and trailing blanks stripped off *)
  166. function blankStr(str : String) : String;
  167.   (* returns string of same length as str, with all non-whitespace characters
  168.      replaced by blanks *)
  169. function intStr(i : Integer) : String;
  170.   (* returns the string representation of i *)
  171. function isInt(str : String; var i : Integer) : Boolean;
  172.   (* checks whether str represents an integer; if so, returns the
  173.      value of it in i *)
  174. function path(filename : String) : String;
  175.   (* returns the path in filename *)
  176. function root(filename : String) : String;
  177.   (* returns root (i.e. extension stripped from filename) of
  178.      filename *)
  179. function addExt(filename, ext : String) : String;
  180.   (* if filename has no extension and last filename character is not '.',
  181.      add extension ext to filename *)
  182. function file_size(filename : String) : LongInt;
  183.   (* determines file size in bytes *)
  184.  
  185. (* Utility functions for list generating routines: *)
  186.  
  187. type CharSet = set of Char;
  188.  
  189. function charStr(c : char; reserved : CharSet) : String;
  190.   (* returns a print name for character c, using the standard escape
  191.      conventions; reserved is the class of `reserved' special characters
  192.      which should be quoted with \ (\ itself is always quoted) *)
  193. function singleQuoteStr(str : String) : String;
  194.   (* returns print name of str enclosed in single quotes, using the
  195.      standard escape conventions *)
  196. function doubleQuoteStr(str : String) : String;
  197.   (* returns print name of str enclosed in double quotes, using the
  198.      standard escape conventions *)
  199.  
  200. implementation
  201.  
  202. uses YaccMsgs;
  203.  
  204. (* String pointers: *)
  205.  
  206. function newStr(str : String) : StrPtr;
  207.   var strp : StrPtr;
  208.   begin
  209.     getmem(strp, succ(length(str)));
  210.     move(str, strp^, succ(length(str)));
  211.     newStr := strp;
  212.   end(*newStr*);
  213.  
  214. (* Integer sets: *)
  215.  
  216. procedure empty(var M : IntSet);
  217.   begin
  218.     M[0] := 0;
  219.   end(*empty*);
  220.  
  221. procedure singleton(var M : IntSet; i : Integer);
  222.   begin
  223.     M[0] := 1; M[1] := i;
  224.   end(*singleton*);
  225.  
  226. procedure include(var M : IntSet; i : Integer);
  227.   var l, r, k : Integer;
  228.   begin
  229.     (* binary search: *)
  230.     l := 1; r := M[0];
  231.     k := l + (r-l) div 2;
  232.     while (l<r) and (M[k]<>i) do
  233.       begin
  234.         if M[k]<i then
  235.           l := succ(k)
  236.         else
  237.           r := pred(k);
  238.         k := l + (r-l) div 2;
  239.       end;
  240.     if (k>M[0]) or (M[k]<>i) then
  241.       begin
  242.         if M[0]>=max_elems then fatal(intset_overflow);
  243.         if (k<=M[0]) and (M[k]<i) then
  244.           begin
  245.             move(M[k+1], M[k+2], (M[0]-k)*sizeOf(Integer));
  246.             M[k+1] := i;
  247.           end
  248.         else
  249.           begin
  250.             move(M[k], M[k+1], (M[0]-k+1)*sizeOf(Integer));
  251.             M[k] := i;
  252.           end;
  253.         inc(M[0]);
  254.       end;
  255.   end(*include*);
  256.  
  257. procedure exclude(var M : IntSet; i : Integer);
  258.   var l, r, k : Integer;
  259.   begin
  260.     (* binary search: *)
  261.     l := 1; r := M[0];
  262.     k := l + (r-l) div 2;
  263.     while (l<r) and (M[k]<>i) do
  264.       begin
  265.         if M[k]<i then
  266.           l := succ(k)
  267.         else
  268.           r := pred(k);
  269.         k := l + (r-l) div 2;
  270.       end;
  271.     if (k<=M[0]) and (M[k]=i) then
  272.       begin
  273.         move(M[k+1], M[k], (M[0]-k)*sizeOf(Integer));
  274.         dec(M[0]);
  275.       end;
  276.   end(*exclude*);
  277.  
  278. procedure setunion(var M, N : IntSet);
  279.   var
  280.     K : IntSet;
  281.     i, j, i_M, i_N : Integer;
  282.   begin
  283.     (* merge sort: *)
  284.     i := 0; i_M := 1; i_N := 1;
  285.     while (i_M<=M[0]) and (i_N<=N[0]) do
  286.       begin
  287.         inc(i);
  288.         if i>max_elems then fatal(intset_overflow);
  289.         if M[i_M]<N[i_N] then
  290.           begin
  291.             K[i] := M[i_M]; inc(i_M);
  292.           end
  293.         else if N[i_N]<M[i_M] then
  294.           begin
  295.             K[i] := N[i_N]; inc(i_N);
  296.           end
  297.         else
  298.           begin
  299.             K[i] := M[i_M]; inc(i_M); inc(i_N);
  300.           end
  301.       end;
  302.     for j := i_M to M[0] do
  303.       begin
  304.         inc(i);
  305.         if i>max_elems then fatal(intset_overflow);
  306.         K[i] := M[j];
  307.       end;
  308.     for j := i_N to N[0] do
  309.       begin
  310.         inc(i);
  311.         if i>max_elems then fatal(intset_overflow);
  312.         K[i] := N[j];
  313.       end;
  314.     K[0] := i;
  315.     move(K, M, succ(i)*sizeOf(Integer));
  316.   end(*setunion*);
  317.  
  318. procedure setminus(var M, N : IntSet);
  319.   var
  320.     K : IntSet;
  321.     i, i_M, i_N : Integer;
  322.   begin
  323.     i := 0; i_N := 1;
  324.     for i_M := 1 to M[0] do
  325.       begin
  326.         while (i_N<=N[0]) and (N[i_N]<M[i_M]) do inc(i_N);
  327.         if (i_N>N[0]) or (N[i_N]>M[i_M]) then
  328.           begin
  329.             inc(i);
  330.             K[i] := M[i_M];
  331.           end
  332.         else
  333.           inc(i_N);
  334.       end;
  335.     K[0] := i;
  336.     move(K, M, succ(i)*sizeOf(Integer));
  337.   end(*setminus*);
  338.  
  339. procedure intersect(var M, N : IntSet);
  340.   var
  341.     K : IntSet;
  342.     i, i_M, i_N : Integer;
  343.   begin
  344.     i := 0; i_N := 1;
  345.     for i_M := 1 to M[0] do
  346.       begin
  347.         while (i_N<=N[0]) and (N[i_N]<M[i_M]) do inc(i_N);
  348.         if (i_N<=N[0]) and (N[i_N]=M[i_M]) then
  349.           begin
  350.             inc(i);
  351.             K[i] := M[i_M];
  352.             inc(i_N);
  353.           end
  354.       end;
  355.     K[0] := i;
  356.     move(K, M, succ(i)*sizeOf(Integer));
  357.   end(*intersect*);
  358.  
  359. function size(var M : IntSet) : Integer;
  360.   begin
  361.     size := M[0]
  362.   end(*size*);
  363.  
  364. function member(i : Integer; var M : IntSet) : Boolean;
  365.   var l, r, k : Integer;
  366.   begin
  367.     (* binary search: *)
  368.     l := 1; r := M[0];
  369.     k := l + (r-l) div 2;
  370.     while (l<r) and (M[k]<>i) do
  371.       begin
  372.         if M[k]<i then
  373.           l := succ(k)
  374.         else
  375.           r := pred(k);
  376.         k := l + (r-l) div 2;
  377.       end;
  378.     member := (k<=M[0]) and (M[k]=i);
  379.   end(*member*);
  380.  
  381. function isempty(var M : IntSet) : Boolean;
  382.   begin
  383.     isempty := M[0]=0
  384.   end(*isempty*);
  385.  
  386. function equal(var M, N : IntSet) : Boolean;
  387.   var i : Integer;
  388.   begin
  389.     if M[0]<>N[0] then
  390.       equal := false
  391.     else
  392.       begin
  393.         for i := 1 to M[0] do
  394.           if M[i]<>N[i] then
  395.             begin
  396.               equal := false;
  397.               exit
  398.             end;
  399.         equal := true
  400.       end
  401.   end(*equal*);
  402.  
  403. function subseteq(var M, N : IntSet) : Boolean;
  404.   var
  405.     i_M, i_N : Integer;
  406.   begin
  407.     if M[0]>N[0] then
  408.       subseteq := false
  409.     else
  410.       begin
  411.         i_N := 1;
  412.         for i_M := 1 to M[0] do
  413.           begin
  414.             while (i_N<=N[0]) and (N[i_N]<M[i_M]) do inc(i_N);
  415.             if (i_N>N[0]) or (N[i_N]>M[i_M]) then
  416.               begin
  417.                 subseteq := false;
  418.                 exit
  419.               end
  420.             else
  421.               inc(i_N);
  422.           end;
  423.         subseteq := true
  424.       end;
  425.   end(*subseteq*);
  426.  
  427. function newIntSet ( var M : IntSet ) : IntSetPtr;
  428.   var
  429.     MP : IntSetPtr;
  430.   begin
  431.     getmem(MP, (size(M)+1)*sizeOf(Integer));
  432.     move(M, MP^, (size(M)+1)*sizeOf(Integer));
  433.   end(*newIntSet*);
  434.  
  435. function newEmptyIntSet : IntSetPtr;
  436.   var
  437.     MP : IntSetPtr;
  438.   begin
  439.     getmem(MP, (max_elems+1)*sizeOf(Integer));
  440.     MP^[0] := 0;
  441.     newEmptyIntSet := MP
  442.   end(*newEmptyIntSet*);
  443.  
  444. (* Quicksort: *)
  445.  
  446. procedure quicksort(lo, hi: Integer;
  447.                     less : OrderPredicate;
  448.                     swap : SwapProc);
  449.   (* derived from the quicksort routine in QSORT.PAS in the Turbo Pascal
  450.      distribution *)
  451.   procedure sort(l, r: Integer);
  452.     var i, j, k : Integer;
  453.     begin
  454.       i := l; j := r; k := (l+r) DIV 2;
  455.       repeat
  456.         while less(i, k) do inc(i);
  457.         while less(k, j) do dec(j);
  458.         if i<=j then
  459.           begin
  460.             swap(i, j);
  461.             if k=i then k := j (* pivot element swapped! *)
  462.             else if k=j then k := i;
  463.             inc(i); dec(j);
  464.           end;
  465.       until i>j;
  466.       if l<j then sort(l,j);
  467.       if i<r then sort(i,r);
  468.     end(*sort*);
  469.   begin
  470.     if lo<hi then sort(lo,hi);
  471.   end(*quicksort*);
  472.  
  473. (* Generic hash table routines: *)
  474.  
  475. function hash(str : String; table_size : Integer) : Integer;
  476.   (* computes a hash key for str *)
  477.   var i, key : Integer;
  478.   begin
  479.     key := 0;
  480.     for i := 1 to length(str) do
  481.       inc(key, ord(str[i]));
  482.     hash := key mod table_size + 1;
  483.   end(*hash*);
  484.  
  485. procedure newPos(var pos, incr, count : Integer; table_size : Integer);
  486.   (* computes a new position in the table (quadratic collision strategy)
  487.      - pos: current position (+inc)
  488.      - incr: current increment (+2)
  489.      - count: current number of collisions (+1)
  490.      quadratic collision formula for position of str after n collisions:
  491.        pos(str, n) = (hash(str)+n^2) mod table_size +1
  492.      note that n^2-(n-1)^2 = 2n-1 <=> n^2 = (n-1)^2 + (2n-1) for n>0,
  493.      i.e. the increment inc=2n-1 increments by two in each collision *)
  494.   begin
  495.     inc(count);
  496.     inc(pos, incr);
  497.     if pos>table_size then pos := pos mod table_size + 1;
  498.     inc(incr, 2)
  499.   end(*newPos*);
  500.  
  501. function key(symbol : String;
  502.              table_size : Integer;
  503.              lookup : TableLookupProc;
  504.              entry  : TableEntryProc) : Integer;
  505.   var pos, incr, count : Integer;
  506.   begin
  507.     pos := hash(symbol, table_size);
  508.     incr := 1;
  509.     count := 0;
  510.     while count<=table_size do
  511.       if lookup(pos)='' then
  512.         begin
  513.           entry(pos, symbol);
  514.           key := pos;
  515.           exit
  516.         end
  517.       else if lookup(pos)=symbol then
  518.         begin
  519.           key := pos;
  520.           exit
  521.         end
  522.       else
  523.         newPos(pos, incr, count, table_size);
  524.     fatal(sym_table_overflow)
  525.   end(*key*);
  526.  
  527. function definedKey(symbol : String;
  528.                     table_size : Integer;
  529.                     lookup : TableLookupProc) : Boolean;
  530.   var pos, incr, count : Integer;
  531.   begin
  532.     pos := hash(symbol, table_size);
  533.     incr := 1;
  534.     count := 0;
  535.     while count<=table_size do
  536.       if lookup(pos)='' then
  537.         begin
  538.           definedKey := false;
  539.           exit
  540.         end
  541.       else if lookup(pos)=symbol then
  542.         begin
  543.           definedKey := true;
  544.           exit
  545.         end
  546.       else
  547.         newPos(pos, incr, count, table_size);
  548.     definedKey := false
  549.   end(*definedKey*);
  550.  
  551. (* Utility routines: *)
  552.  
  553. function min(i, j : Integer) : Integer;
  554.   begin
  555.     if i<j then
  556.       min := i
  557.     else
  558.       min := j
  559.   end(*min*);
  560. function max(i, j : Integer) : Integer;
  561.   begin
  562.     if i>j then
  563.       max := i
  564.     else
  565.       max := j
  566.   end(*max*);
  567. function upper(str : String) : String;
  568.   var i : Integer;
  569.   begin
  570.     for i := 1 to length(str) do
  571.       str[i] := upCase(str[i]);
  572.     upper := str
  573.   end(*upper*);
  574. function strip(str : String) : String;
  575.   begin
  576.     while (length(str)>0) and ((str[1]=' ') or (str[1]=tab)) do
  577.       delete(str, 1, 1);
  578.     while (length(str)>0) and
  579.           ((str[length(str)]= ' ') or
  580.            (str[length(str)]=tab)) do
  581.       delete(str, length(str), 1);
  582.     strip := str;
  583.   end(*strip*);
  584. function blankStr(str : String) : String;
  585.   var i : Integer;
  586.   begin
  587.     for i := 1 to length(str) do
  588.       if str[i]<>tab then str[i] := ' ';
  589.     blankStr := str;
  590.   end(*blankStr*);
  591. function intStr(i : Integer) : String;
  592.   var s : String;
  593.   begin
  594.     str(i, s);
  595.     intStr := s
  596.   end(*intStr*);
  597. function isInt(str : String; var i : Integer) : Boolean;
  598.   var result : Integer;
  599.   begin
  600.     val(str, i, result);
  601.     isInt := result = 0;
  602.   end(*isInt*);
  603. function path(filename : String) : String;
  604.   var i : Integer;
  605.   begin
  606.     i := length(filename);
  607.     while (i>0) and (filename[i]<>'\') and (filename[i]<>':') do
  608.       dec(i);
  609.     path := copy(filename, 1, i);
  610.   end(*path*);
  611. function root(filename : String) : String;
  612.   var
  613.     i : Integer;
  614.   begin
  615.     root := filename;
  616.     for i := length(filename) downto 1 do
  617.       case filename[i] of
  618.         '.' :
  619.           begin
  620.             root := copy(filename, 1, i-1);
  621.             exit
  622.           end;
  623.         '\': exit;
  624.         else
  625.       end;
  626.   end(*addExt*);
  627. function addExt(filename, ext : String) : String;
  628.   (* implemented with goto for maximum efficiency *)
  629.   label x;
  630.   var
  631.     i : Integer;
  632.   begin
  633.     addExt := filename;
  634.     for i := length(filename) downto 1 do
  635.       case filename[i] of
  636.         '.' : exit;
  637.         '\': goto x;
  638.         else
  639.       end;
  640.     x : addExt := filename+'.'+ext
  641.   end(*addExt*);
  642. function file_size(filename : String) : LongInt;
  643.   var f : File;
  644.   begin
  645.     assign(f, filename);
  646.     reset(f, 1);
  647.     if ioresult=0 then
  648.       file_size := fileSize(f)
  649.     else
  650.       file_size := 0;
  651.     close(f);
  652.   end(*file_size*);
  653.  
  654. (* Utility functions for list generating routines: *)
  655.  
  656. function charStr(c : char; reserved : CharSet) : String;
  657.   function octStr(c : char) : String;
  658.     (* return octal string representation of character c *)
  659.     begin
  660.       octStr := intStr(ord(c) div 64)+intStr((ord(c) mod 64) div 8)+
  661.                 intStr(ord(c) mod 8);
  662.     end(*octStr*);
  663.   begin
  664.     case c of
  665.       #0..#7,      (* nonprintable characters *)
  666.       #11..#31,
  667.       #127..#255 : charStr := '\'+octStr(c);
  668.       bs         : charStr := '\b';
  669.       tab        : charStr := '\t';
  670.       nl         : charStr := '\n';
  671.       cr         : charStr := '\c';
  672.       ff         : charStr := '\f';
  673.       '\'        : charStr := '\\';
  674.       else if c in reserved then
  675.         charStr := '\'+c
  676.       else
  677.         charStr := c
  678.     end
  679.   end(*charStr*);
  680.  
  681. function singleQuoteStr(str : String) : String;
  682.   var
  683.     i : Integer;
  684.     str1 : String;
  685.   begin
  686.     str1 := '';
  687.     for i := 1 to length(str) do
  688.       str1 := str1+charStr(str[i], ['''']);
  689.     singleQuoteStr := ''''+str1+''''
  690.   end(*singleQuoteStr*);
  691.  
  692. function doubleQuoteStr(str : String) : String;
  693.   var
  694.     i : Integer;
  695.     str1 : String;
  696.   begin
  697.     str1 := '';
  698.     for i := 1 to length(str) do
  699.       str1 := str1+charStr(str[i], ['"']);
  700.     doubleQuoteStr := '"'+str1+'"'
  701.   end(*doubleQuoteStr*);
  702.  
  703. end(*YaccBase*).